////-----------------------------------------------------------------------------
//// File: DXUtil.cpp
////
//// Desc: Shortcut macros and functions for using DX objects
////
//// Copyright (c) Microsoft Corporation. All rights reserved
////-----------------------------------------------------------------------------
//#ifndef STRICT
//#define STRICT
//#endif // !STRICT
//#include <windows.h>
//#include <mmsystem.h>
//#include <tchar.h>
//#include <stdio.h> 
//#include <stdarg.h>
//#include "DXUtil.h"
//
//
//#ifdef UNICODE
//    typedef HINSTANCE (WINAPI* LPShellExecute)(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd);
//#else
//    typedef HINSTANCE (WINAPI* LPShellExecute)(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd);
//#endif
//
//
//#ifndef UNDER_CE
////-----------------------------------------------------------------------------
//// Name: DXUtil_GetDXSDKMediaPathCch()
//// Desc: Returns the DirectX SDK media path
////       cchDest is the size in TCHARs of strDest.  Be careful not to 
////       pass in sizeof(strDest) on UNICODE builds.
////-----------------------------------------------------------------------------
//HRESULT DXUtil_GetDXSDKMediaPathCch( TCHAR* strDest, int cchDest )
//{
//    if( strDest == NULL || cchDest < 1 )
//        return E_INVALIDARG;
//
//    lstrcpy( strDest, TEXT("") );
//
//    // Open the appropriate registry key
//    HKEY  hKey;
//    LONG lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
//                                _T("Software\\Microsoft\\DirectX SDK"),
//                                0, KEY_READ, &hKey );
//    if( ERROR_SUCCESS != lResult )
//        return E_FAIL;
//
//    DWORD dwType;
//    DWORD dwSize = cchDest * sizeof(TCHAR);
//    lResult = RegQueryValueEx( hKey, _T("DX9SDK Samples Path"), NULL,
//                              &dwType, (BYTE*)strDest, &dwSize );
//    strDest[cchDest-1] = 0; // RegQueryValueEx doesn't NULL term if buffer too small
//    RegCloseKey( hKey );
//
//    if( ERROR_SUCCESS != lResult )
//        return E_FAIL;
//
//    const TCHAR* strMedia = _T("\\Media\\");
//    if( lstrlen(strDest) + lstrlen(strMedia) < cchDest )
//        _tcscat( strDest, strMedia );
//    else
//        return E_INVALIDARG;
//
//    return S_OK;
//}
//#endif // !UNDER_CE
//
//
//
//#ifndef UNDER_CE
////-----------------------------------------------------------------------------
//// Name: DXUtil_FindMediaFileCch()
//// Desc: Returns a valid path to a DXSDK media file
////       cchDest is the size in TCHARs of strDestPath.  Be careful not to 
////       pass in sizeof(strDest) on UNICODE builds.
////-----------------------------------------------------------------------------
//HRESULT DXUtil_FindMediaFileCch( TCHAR* strDestPath, int cchDest, TCHAR* strFilename )
//{
//    HRESULT hr;
//    HANDLE file;
//    TCHAR* strShortNameTmp = NULL;
//    TCHAR strShortName[MAX_PATH];
//    int cchPath;
//
//    if( NULL==strFilename || NULL==strDestPath || cchDest < 1 )
//        return E_INVALIDARG;
//
//    lstrcpy( strDestPath, TEXT("") );
//    lstrcpy( strShortName, TEXT("") );
//
//    // Build full path name from strFileName (strShortName will be just the leaf filename)
//    cchPath = GetFullPathName(strFilename, cchDest, strDestPath, &strShortNameTmp);
//    if ((cchPath == 0) || (cchDest <= cchPath))
//        return E_FAIL;
//    if( strShortNameTmp )
//        lstrcpyn( strShortName, strShortNameTmp, MAX_PATH );
//
//    // first try to find the filename given a full path
//    file = CreateFile( strDestPath, GENERIC_READ, FILE_SHARE_READ, NULL, 
//                       OPEN_EXISTING, 0, NULL );
//    if( INVALID_HANDLE_VALUE != file )
//    {
//        CloseHandle( file );
//        return S_OK;
//    }
//    
//    // next try to find the filename in the current working directory (path stripped)
//    file = CreateFile( strShortName, GENERIC_READ, FILE_SHARE_READ, NULL, 
//                       OPEN_EXISTING, 0, NULL );
//    if( INVALID_HANDLE_VALUE != file )
//    {
//        _tcsncpy( strDestPath, strShortName, cchDest );
//        strDestPath[cchDest-1] = 0; // _tcsncpy doesn't NULL term if it runs out of space
//        CloseHandle( file );
//        return S_OK;
//    }
//    
//    // last, check if the file exists in the media directory
//    if( FAILED( hr = DXUtil_GetDXSDKMediaPathCch( strDestPath, cchDest ) ) )
//        return hr;
//
//    if( lstrlen(strDestPath) + lstrlen(strShortName) < cchDest )
//        lstrcat( strDestPath, strShortName );
//    else
//        return E_INVALIDARG;
//
//    file = CreateFile( strDestPath, GENERIC_READ, FILE_SHARE_READ, NULL, 
//                       OPEN_EXISTING, 0, NULL );
//    if( INVALID_HANDLE_VALUE != file )
//    {
//        CloseHandle( file );
//        return S_OK;
//    }
//
//    // On failure, just return the file as the path
//    _tcsncpy( strDestPath, strFilename, cchDest );
//    strDestPath[cchDest-1] = 0; // _tcsncpy doesn't NULL term if it runs out of space
//    return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
//}
//#endif // !UNDER_CE
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_ReadStringRegKeyCch()
//// Desc: Helper function to read a registry key string
////       cchDest is the size in TCHARs of strDest.  Be careful not to 
////       pass in sizeof(strDest) on UNICODE builds.
////-----------------------------------------------------------------------------
//HRESULT DXUtil_ReadStringRegKeyCch( HKEY hKey, TCHAR* strRegName, TCHAR* strDest, 
//                                    DWORD cchDest, TCHAR* strDefault )
//{
//    DWORD dwType;
//    DWORD cbDest = cchDest * sizeof(TCHAR);
//
//    if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, 
//                                          (BYTE*)strDest, &cbDest ) )
//    {
//        _tcsncpy( strDest, strDefault, cchDest );
//        strDest[cchDest-1] = 0;
//
//        if( dwType != REG_SZ )
//            return E_FAIL;
//
//        return S_OK;
//    }
//
//    return E_FAIL;
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_WriteStringRegKey()
//// Desc: Helper function to write a registry key string
////-----------------------------------------------------------------------------
//HRESULT DXUtil_WriteStringRegKey( HKEY hKey, TCHAR* strRegName,
//                                  TCHAR* strValue )
//{
//    if( NULL == strValue )
//        return E_INVALIDARG;
//        
//    DWORD cbValue = ((DWORD)_tcslen(strValue)+1) * sizeof(TCHAR);
//
//    if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_SZ, 
//                                        (BYTE*)strValue, cbValue ) )
//        return E_FAIL;
//
//    return S_OK;
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_ReadIntRegKey()
//// Desc: Helper function to read a registry key int
////-----------------------------------------------------------------------------
//HRESULT DXUtil_ReadIntRegKey( HKEY hKey, TCHAR* strRegName, DWORD* pdwDest, 
//                              DWORD dwDefault )
//{
//    DWORD dwType;
//    DWORD dwLength = sizeof(DWORD);
//
//    if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, 
//                                          (BYTE*)pdwDest, &dwLength ) )
//    {
//        *pdwDest = dwDefault;
//        if( dwType != REG_DWORD )
//            return E_FAIL;
//
//        return S_OK;
//    }
//
//    return E_FAIL;
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_WriteIntRegKey()
//// Desc: Helper function to write a registry key int
////-----------------------------------------------------------------------------
//HRESULT DXUtil_WriteIntRegKey( HKEY hKey, TCHAR* strRegName, DWORD dwValue )
//{
//    if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_DWORD, 
//                                        (BYTE*)&dwValue, sizeof(DWORD) ) )
//        return E_FAIL;
//
//    return S_OK;
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_ReadBoolRegKey()
//// Desc: Helper function to read a registry key BOOL
////-----------------------------------------------------------------------------
//HRESULT DXUtil_ReadBoolRegKey( HKEY hKey, TCHAR* strRegName, BOOL* pbDest, 
//                              BOOL bDefault )
//{
//    DWORD dwType;
//    DWORD dwLength = sizeof(BOOL);
//
//    if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, 
//                                          (BYTE*)pbDest, &dwLength ) )
//    {
//        *pbDest = bDefault;
//        if( dwType != REG_DWORD )
//            return E_FAIL;
//
//        return S_OK;
//    }
//
//    return E_FAIL;
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_WriteBoolRegKey()
//// Desc: Helper function to write a registry key BOOL
////-----------------------------------------------------------------------------
//HRESULT DXUtil_WriteBoolRegKey( HKEY hKey, TCHAR* strRegName, BOOL bValue )
//{
//    if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_DWORD, 
//                                        (BYTE*)&bValue, sizeof(BOOL) ) )
//        return E_FAIL;
//
//    return S_OK;
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_ReadGuidRegKey()
//// Desc: Helper function to read a registry key guid
////-----------------------------------------------------------------------------
//HRESULT DXUtil_ReadGuidRegKey( HKEY hKey, TCHAR* strRegName, GUID* pGuidDest, 
//                               GUID& guidDefault )
//{
//    DWORD dwType;
//    DWORD dwLength = sizeof(GUID);
//
//    if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, 
//                                          (LPBYTE) pGuidDest, &dwLength ) )
//    {
//        *pGuidDest = guidDefault;
//        if( dwType != REG_BINARY )
//            return E_FAIL;
//
//        return S_OK;
//    }
//
//    return E_FAIL;
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_WriteGuidRegKey()
//// Desc: Helper function to write a registry key guid
////-----------------------------------------------------------------------------
//HRESULT DXUtil_WriteGuidRegKey( HKEY hKey, TCHAR* strRegName, GUID guidValue )
//{
//    if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_BINARY, 
//                                        (BYTE*)&guidValue, sizeof(GUID) ) )
//        return E_FAIL;
//
//    return S_OK;
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_Timer()
//// Desc: Performs timer opertations. Use the following commands:
////          TIMER_RESET           - to reset the timer
////          TIMER_START           - to start the timer
////          TIMER_STOP            - to stop (or pause) the timer
////          TIMER_ADVANCE         - to advance the timer by 0.1 seconds
////          TIMER_GETABSOLUTETIME - to get the absolute system time
////          TIMER_GETAPPTIME      - to get the current time
////          TIMER_GETELAPSEDTIME  - to get the time that elapsed between 
////                                  TIMER_GETELAPSEDTIME calls
////-----------------------------------------------------------------------------
//FLOAT __stdcall DXUtil_Timer( TIMER_COMMAND command )
//{
//    static BOOL     m_bTimerInitialized = FALSE;
//    static BOOL     m_bUsingQPF         = FALSE;
//    static BOOL     m_bTimerStopped     = TRUE;
//    static LONGLONG m_llQPFTicksPerSec  = 0;
//
//    // Initialize the timer
//    if( FALSE == m_bTimerInitialized )
//    {
//        m_bTimerInitialized = TRUE;
//
//        // Use QueryPerformanceFrequency() to get frequency of timer.  If QPF is
//        // not supported, we will timeGetTime() which returns milliseconds.
//        LARGE_INTEGER qwTicksPerSec;
//        m_bUsingQPF = QueryPerformanceFrequency( &qwTicksPerSec );
//        if( m_bUsingQPF )
//            m_llQPFTicksPerSec = qwTicksPerSec.QuadPart;
//    }
//
//    if( m_bUsingQPF )
//    {
//        static LONGLONG m_llStopTime        = 0;
//        static LONGLONG m_llLastElapsedTime = 0;
//        static LONGLONG m_llBaseTime        = 0;
//        double fTime;
//        double fElapsedTime;
//        LARGE_INTEGER qwTime;
//        
//        // Get either the current time or the stop time, depending
//        // on whether we're stopped and what command was sent
//        if( m_llStopTime != 0 && command != TIMER_START && command != TIMER_GETABSOLUTETIME)
//            qwTime.QuadPart = m_llStopTime;
//        else
//            QueryPerformanceCounter( &qwTime );
//
//        // Return the elapsed time
//        if( command == TIMER_GETELAPSEDTIME )
//        {
//            fElapsedTime = (double) ( qwTime.QuadPart - m_llLastElapsedTime ) / (double) m_llQPFTicksPerSec;
//            m_llLastElapsedTime = qwTime.QuadPart;
//            return (FLOAT) fElapsedTime;
//        }
//    
//        // Return the current time
//        if( command == TIMER_GETAPPTIME )
//        {
//            double fAppTime = (double) ( qwTime.QuadPart - m_llBaseTime ) / (double) m_llQPFTicksPerSec;
//            return (FLOAT) fAppTime;
//        }
//    
//        // Reset the timer
//        if( command == TIMER_RESET )
//        {
//            m_llBaseTime        = qwTime.QuadPart;
//            m_llLastElapsedTime = qwTime.QuadPart;
//            m_llStopTime        = 0;
//            m_bTimerStopped     = FALSE;
//            return 0.0f;
//        }
//    
//        // Start the timer
//        if( command == TIMER_START )
//        {
//            if( m_bTimerStopped )
//                m_llBaseTime += qwTime.QuadPart - m_llStopTime;
//            m_llStopTime = 0;
//            m_llLastElapsedTime = qwTime.QuadPart;
//            m_bTimerStopped = FALSE;
//            return 0.0f;
//        }
//    
//        // Stop the timer
//        if( command == TIMER_STOP )
//        {
//            if( !m_bTimerStopped )
//            {
//                m_llStopTime = qwTime.QuadPart;
//                m_llLastElapsedTime = qwTime.QuadPart;
//                m_bTimerStopped = TRUE;
//            }
//            return 0.0f;
//        }
//    
//        // Advance the timer by 1/10th second
//        if( command == TIMER_ADVANCE )
//        {
//            m_llStopTime += m_llQPFTicksPerSec/10;
//            return 0.0f;
//        }
//
//        if( command == TIMER_GETABSOLUTETIME )
//        {
//            fTime = qwTime.QuadPart / (double) m_llQPFTicksPerSec;
//            return (FLOAT) fTime;
//        }
//
//        return -1.0f; // Invalid command specified
//    }
//    else
//    {
//        // Get the time using timeGetTime()
//        static double m_fLastElapsedTime  = 0.0;
//        static double m_fBaseTime         = 0.0;
//        static double m_fStopTime         = 0.0;
//        double fTime;
//        double fElapsedTime;
//        
//        // Get either the current time or the stop time, depending
//        // on whether we're stopped and what command was sent
//        if( m_fStopTime != 0.0 && command != TIMER_START && command != TIMER_GETABSOLUTETIME)
//            fTime = m_fStopTime;
//        else
//            fTime = GETTIMESTAMP() * 0.001;
//    
//        // Return the elapsed time
//        if( command == TIMER_GETELAPSEDTIME )
//        {   
//            fElapsedTime = (double) (fTime - m_fLastElapsedTime);
//            m_fLastElapsedTime = fTime;
//            return (FLOAT) fElapsedTime;
//        }
//    
//        // Return the current time
//        if( command == TIMER_GETAPPTIME )
//        {
//            return (FLOAT) (fTime - m_fBaseTime);
//        }
//    
//        // Reset the timer
//        if( command == TIMER_RESET )
//        {
//            m_fBaseTime         = fTime;
//            m_fLastElapsedTime  = fTime;
//            m_fStopTime         = 0;
//            m_bTimerStopped     = FALSE;
//            return 0.0f;
//        }
//    
//        // Start the timer
//        if( command == TIMER_START )
//        {
//            if( m_bTimerStopped )
//                m_fBaseTime += fTime - m_fStopTime;
//            m_fStopTime = 0.0f;
//            m_fLastElapsedTime  = fTime;
//            m_bTimerStopped = FALSE;
//            return 0.0f;
//        }
//    
//        // Stop the timer
//        if( command == TIMER_STOP )
//        {
//            if( !m_bTimerStopped )
//            {
//                m_fStopTime = fTime;
//                m_fLastElapsedTime  = fTime;
//                m_bTimerStopped = TRUE;
//            }
//            return 0.0f;
//        }
//    
//        // Advance the timer by 1/10th second
//        if( command == TIMER_ADVANCE )
//        {
//            m_fStopTime += 0.1f;
//            return 0.0f;
//        }
//
//        if( command == TIMER_GETABSOLUTETIME )
//        {
//            return (FLOAT) fTime;
//        }
//
//        return -1.0f; // Invalid command specified
//    }
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_ConvertAnsiStringToWideCch()
//// Desc: This is a UNICODE conversion utility to convert a CHAR string into a
////       WCHAR string. 
////       cchDestChar is the size in TCHARs of wstrDestination.  Be careful not to 
////       pass in sizeof(strDest) 
////-----------------------------------------------------------------------------
//HRESULT DXUtil_ConvertAnsiStringToWideCch( WCHAR* wstrDestination, const CHAR* strSource, 
//                                     int cchDestChar )
//{
//    if( wstrDestination==NULL || strSource==NULL || cchDestChar < 1 )
//        return E_INVALIDARG;
//
//    int nResult = MultiByteToWideChar( CP_ACP, 0, strSource, -1, 
//                                       wstrDestination, cchDestChar );
//    wstrDestination[cchDestChar-1] = 0;
//    
//    if( nResult == 0 )
//        return E_FAIL;
//    return S_OK;
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_ConvertWideStringToAnsi()
//// Desc: This is a UNICODE conversion utility to convert a WCHAR string into a
////       CHAR string. 
////       cchDestChar is the size in TCHARs of strDestination
////-----------------------------------------------------------------------------
//HRESULT DXUtil_ConvertWideStringToAnsiCch( CHAR* strDestination, const WCHAR* wstrSource, 
//                                     int cchDestChar )
//{
//    if( strDestination==NULL || wstrSource==NULL || cchDestChar < 1 )
//        return E_INVALIDARG;
//
//    int nResult = WideCharToMultiByte( CP_ACP, 0, wstrSource, -1, strDestination, 
//                                       cchDestChar*sizeof(CHAR), NULL, NULL );
//    strDestination[cchDestChar-1] = 0;
//    
//    if( nResult == 0 )
//        return E_FAIL;
//    return S_OK;
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_ConvertGenericStringToAnsi()
//// Desc: This is a UNICODE conversion utility to convert a TCHAR string into a
////       CHAR string. 
////       cchDestChar is the size in TCHARs of strDestination
////-----------------------------------------------------------------------------
//HRESULT DXUtil_ConvertGenericStringToAnsiCch( CHAR* strDestination, const TCHAR* tstrSource, 
//                                           int cchDestChar )
//{
//    if( strDestination==NULL || tstrSource==NULL || cchDestChar < 1 )
//        return E_INVALIDARG;
//
//#ifdef _UNICODE
//    return DXUtil_ConvertWideStringToAnsiCch( strDestination, tstrSource, cchDestChar );
//#else
//    strncpy( strDestination, tstrSource, cchDestChar );
//    strDestination[cchDestChar-1] = '\0';
//    return S_OK;
//#endif   
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_ConvertGenericStringToWide()
//// Desc: This is a UNICODE conversion utility to convert a TCHAR string into a
////       WCHAR string. 
////       cchDestChar is the size in TCHARs of wstrDestination.  Be careful not to 
////       pass in sizeof(strDest) 
////-----------------------------------------------------------------------------
//HRESULT DXUtil_ConvertGenericStringToWideCch( WCHAR* wstrDestination, const TCHAR* tstrSource, 
//                                           int cchDestChar )
//{
//    if( wstrDestination==NULL || tstrSource==NULL || cchDestChar < 1 )
//        return E_INVALIDARG;
//
//#ifdef _UNICODE
//    wcsncpy( wstrDestination, tstrSource, cchDestChar );
//    wstrDestination[cchDestChar-1] = L'\0';
//    return S_OK;
//#else
//    return DXUtil_ConvertAnsiStringToWideCch( wstrDestination, tstrSource, cchDestChar );
//#endif    
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_ConvertAnsiStringToGeneric()
//// Desc: This is a UNICODE conversion utility to convert a CHAR string into a
////       TCHAR string. 
////       cchDestChar is the size in TCHARs of tstrDestination.  Be careful not to 
////       pass in sizeof(strDest) on UNICODE builds
////-----------------------------------------------------------------------------
//HRESULT DXUtil_ConvertAnsiStringToGenericCch( TCHAR* tstrDestination, const CHAR* strSource, 
//                                           int cchDestChar )
//{
//    if( tstrDestination==NULL || strSource==NULL || cchDestChar < 1 )
//        return E_INVALIDARG;
//        
//#ifdef _UNICODE
//    return DXUtil_ConvertAnsiStringToWideCch( tstrDestination, strSource, cchDestChar );
//#else
//    strncpy( tstrDestination, strSource, cchDestChar );
//    tstrDestination[cchDestChar-1] = '\0';
//    return S_OK;
//#endif    
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_ConvertAnsiStringToGeneric()
//// Desc: This is a UNICODE conversion utility to convert a WCHAR string into a
////       TCHAR string. 
////       cchDestChar is the size in TCHARs of tstrDestination.  Be careful not to 
////       pass in sizeof(strDest) on UNICODE builds
////-----------------------------------------------------------------------------
//HRESULT DXUtil_ConvertWideStringToGenericCch( TCHAR* tstrDestination, const WCHAR* wstrSource, 
//                                           int cchDestChar )
//{
//    if( tstrDestination==NULL || wstrSource==NULL || cchDestChar < 1 )
//        return E_INVALIDARG;
//
//#ifdef _UNICODE
//    wcsncpy( tstrDestination, wstrSource, cchDestChar );
//    tstrDestination[cchDestChar-1] = L'\0';    
//    return S_OK;
//#else
//    return DXUtil_ConvertWideStringToAnsiCch( tstrDestination, wstrSource, cchDestChar );
//#endif
//}
//
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_LaunchReadme()
//// Desc: Finds and opens the readme.txt for this sample
////-----------------------------------------------------------------------------
//VOID DXUtil_LaunchReadme( HWND hWnd, TCHAR* strLoc )
//{
//
//#ifdef UNDER_CE
//    // This is not available on PocketPC
//    MessageBox( hWnd, TEXT("For operating instructions, please open the ")
//                      TEXT("readme.txt file included with the project."),
//                TEXT("DirectX SDK Sample"), MB_ICONWARNING | MB_OK );
//
//    return;
//#else 
//
//    bool bSuccess = false;
//    bool bFound = false;
//    TCHAR strReadmePath[1024];
//    TCHAR strExeName[MAX_PATH];
//    TCHAR strExePath[MAX_PATH];
//    TCHAR strSamplePath[MAX_PATH];
//    TCHAR* strLastSlash = NULL;
//
//    lstrcpy( strReadmePath, TEXT("") );
//    lstrcpy( strExePath, TEXT("") );
//    lstrcpy( strExeName, TEXT("") );
//    lstrcpy( strSamplePath, TEXT("") );
//
//    // If the user provided a location for the readme, check there first.
//    if( strLoc )
//    {
//        HKEY  hKey;
//        LONG lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
//                                    _T("Software\\Microsoft\\DirectX SDK"),
//                                    0, KEY_READ, &hKey );
//        if( ERROR_SUCCESS == lResult )
//        {
//            DWORD dwType;
//            DWORD dwSize = MAX_PATH * sizeof(TCHAR);
//            lResult = RegQueryValueEx( hKey, _T("DX9SDK Samples Path"), NULL,
//                                      &dwType, (BYTE*)strSamplePath, &dwSize );
//            strSamplePath[MAX_PATH-1] = 0; // RegQueryValueEx doesn't NULL term if buffer too small
//            
//            if( ERROR_SUCCESS == lResult )
//            {
//                _sntprintf( strReadmePath, 1023, TEXT("%s\\C++\\%s\\readme.txt"), 
//                            strSamplePath, strLoc );
//                strReadmePath[1023] = 0;
//
//                if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
//                    bFound = TRUE;
//            }
//        }
//
//        RegCloseKey( hKey );
//    }
//
//    // Get the exe name, and exe path
//    GetModuleFileName( NULL, strExePath, MAX_PATH );
//    strExePath[MAX_PATH-1]=0;
//
//    strLastSlash = _tcsrchr( strExePath, TEXT('\\') );
//    if( strLastSlash )
//    {
//        _tcsncpy( strExeName, &strLastSlash[1], MAX_PATH );
//        strExeName[MAX_PATH-1]=0;
//
//        // Chop the exe name from the exe path
//        *strLastSlash = 0;
//
//        // Chop the .exe from the exe name
//        strLastSlash = _tcsrchr( strExeName, TEXT('.') );
//        if( strLastSlash )
//            *strLastSlash = 0;
//    }
//
//    if( !bFound )
//    {
//        // Search in "%EXE_DIR%\..\%EXE_NAME%".  This matchs the DirectX SDK layout
//        _tcscpy( strReadmePath, strExePath );
//
//        strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') );
//        if( strLastSlash )
//            *strLastSlash = 0;
//        lstrcat( strReadmePath, TEXT("\\") );
//        lstrcat( strReadmePath, strExeName );
//        lstrcat( strReadmePath, TEXT("\\readme.txt") );
//        if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
//            bFound = TRUE;
//    }
//
//    if( !bFound )
//    {
//        // Search in "%EXE_DIR%\"
//        _tcscpy( strReadmePath, strExePath );
//        lstrcat( strReadmePath, TEXT("\\readme.txt") );
//        if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
//            bFound = TRUE;
//    }
//
//    if( !bFound )
//    {
//        // Search in "%EXE_DIR%\.."
//        _tcscpy( strReadmePath, strExePath );
//        strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') );
//        if( strLastSlash )
//            *strLastSlash = 0;
//        lstrcat( strReadmePath, TEXT("\\readme.txt") );
//        if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
//            bFound = TRUE;
//    }
//
//    if( !bFound )
//    {
//        // Search in "%EXE_DIR%\..\.."
//        _tcscpy( strReadmePath, strExePath );
//        strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') );
//        if( strLastSlash )
//            *strLastSlash = 0;
//        strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') );
//        if( strLastSlash )
//            *strLastSlash = 0;
//        lstrcat( strReadmePath, TEXT("\\readme.txt") );
//        if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF )
//            bFound = TRUE;
//    }
//
//    if( bFound )
//    {
//        // GetProcAddress for ShellExecute, so we don't have to include shell32.lib 
//        // in every project that uses dxutil.cpp
//        LPShellExecute pShellExecute = NULL;
//        HINSTANCE hInstShell32 = LoadLibrary(TEXT("shell32.dll"));
//        if (hInstShell32 != NULL)
//        {
//#ifdef UNICODE
//            pShellExecute = (LPShellExecute)GetProcAddress(hInstShell32, _TWINCE("ShellExecuteW"));
//#else
//            pShellExecute = (LPShellExecute)GetProcAddress(hInstShell32, _TWINCE("ShellExecuteA"));
//#endif
//            if( pShellExecute != NULL )
//            {
//                if( pShellExecute( hWnd, TEXT("open"), strReadmePath, NULL, NULL, SW_SHOW ) > (HINSTANCE) 32 )
//                    bSuccess = true;
//            }
//
//            FreeLibrary(hInstShell32);
//        }
//    }
//
//    if( !bSuccess )
//    {
//        // Tell the user that the readme couldn't be opened
//        MessageBox( hWnd, TEXT("Could not find readme.txt"), 
//                    TEXT("DirectX SDK Sample"), MB_ICONWARNING | MB_OK );
//    }
//
//#endif // UNDER_CE
//}
//
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_Trace()
//// Desc: Outputs to the debug stream a formatted string with a variable-
////       argument list.
////-----------------------------------------------------------------------------
//VOID DXUtil_Trace( TCHAR* strMsg, ... )
//{
//#if defined(DEBUG) | defined(_DEBUG)
//    TCHAR strBuffer[512];
//    
//    va_list args;
//    va_start(args, strMsg);
//    _vsntprintf( strBuffer, 512, strMsg, args );
//    va_end(args);
//
//    OutputDebugString( strBuffer );
//#else
//    UNREFERENCED_PARAMETER(strMsg);
//#endif
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_ConvertStringToGUID()
//// Desc: Converts a string to a GUID
////-----------------------------------------------------------------------------
//HRESULT DXUtil_ConvertStringToGUID( const TCHAR* strSrc, GUID* pGuidDest )
//{
//    UINT aiTmp[10];
//
//    if( _stscanf( strSrc, TEXT("{%8X-%4X-%4X-%2X%2X-%2X%2X%2X%2X%2X%2X}"),
//                    &pGuidDest->Data1, 
//                    &aiTmp[0], &aiTmp[1], 
//                    &aiTmp[2], &aiTmp[3],
//                    &aiTmp[4], &aiTmp[5],
//                    &aiTmp[6], &aiTmp[7],
//                    &aiTmp[8], &aiTmp[9] ) != 11 )
//    {
//        ZeroMemory( pGuidDest, sizeof(GUID) );
//        return E_FAIL;
//    }
//    else
//    {
//        pGuidDest->Data2       = (USHORT) aiTmp[0];
//        pGuidDest->Data3       = (USHORT) aiTmp[1];
//        pGuidDest->Data4[0]    = (BYTE) aiTmp[2];
//        pGuidDest->Data4[1]    = (BYTE) aiTmp[3];
//        pGuidDest->Data4[2]    = (BYTE) aiTmp[4];
//        pGuidDest->Data4[3]    = (BYTE) aiTmp[5];
//        pGuidDest->Data4[4]    = (BYTE) aiTmp[6];
//        pGuidDest->Data4[5]    = (BYTE) aiTmp[7];
//        pGuidDest->Data4[6]    = (BYTE) aiTmp[8];
//        pGuidDest->Data4[7]    = (BYTE) aiTmp[9];
//        return S_OK;
//    }
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: DXUtil_ConvertGUIDToStringCch()
//// Desc: Converts a GUID to a string 
////       cchDestChar is the size in TCHARs of strDest.  Be careful not to 
////       pass in sizeof(strDest) on UNICODE builds
////-----------------------------------------------------------------------------
//HRESULT DXUtil_ConvertGUIDToStringCch( const GUID* pGuidSrc, TCHAR* strDest, int cchDestChar )
//{
//    int nResult = _sntprintf( strDest, cchDestChar, TEXT("{%0.8X-%0.4X-%0.4X-%0.2X%0.2X-%0.2X%0.2X%0.2X%0.2X%0.2X%0.2X}"),
//               pGuidSrc->Data1, pGuidSrc->Data2, pGuidSrc->Data3,
//               pGuidSrc->Data4[0], pGuidSrc->Data4[1],
//               pGuidSrc->Data4[2], pGuidSrc->Data4[3],
//               pGuidSrc->Data4[4], pGuidSrc->Data4[5],
//               pGuidSrc->Data4[6], pGuidSrc->Data4[7] );
//
//    if( nResult < 0 )
//        return E_FAIL;
//    return S_OK;
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: CArrayList constructor
//// Desc: 
////-----------------------------------------------------------------------------
//CArrayList::CArrayList( ArrayListType Type, UINT BytesPerEntry )
//{
//    if( Type == AL_REFERENCE )
//        BytesPerEntry = sizeof(void*);
//    m_ArrayListType = Type;
//    m_pData = NULL;
//    m_BytesPerEntry = BytesPerEntry;
//    m_NumEntries = 0;
//    m_NumEntriesAllocated = 0;
//}
//
//
//
////-----------------------------------------------------------------------------
//// Name: CArrayList destructor
//// Desc: 
////-----------------------------------------------------------------------------
//CArrayList::~CArrayList( void )
//{
//    if( m_pData != NULL )
//        delete[] m_pData;
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: CArrayList::Add
//// Desc: Adds pEntry to the list.
////-----------------------------------------------------------------------------
//HRESULT CArrayList::Add( void* pEntry )
//{
//    if( m_BytesPerEntry == 0 )
//        return E_FAIL;
//    if( m_pData == NULL || m_NumEntries + 1 > m_NumEntriesAllocated )
//    {
//        void* pDataNew;
//        UINT NumEntriesAllocatedNew;
//        if( m_NumEntriesAllocated == 0 )
//            NumEntriesAllocatedNew = 16;
//        else
//            NumEntriesAllocatedNew = m_NumEntriesAllocated * 2;
//        pDataNew = new BYTE[NumEntriesAllocatedNew * m_BytesPerEntry];
//        if( pDataNew == NULL )
//            return E_OUTOFMEMORY;
//        if( m_pData != NULL )
//        {
//            CopyMemory( pDataNew, m_pData, m_NumEntries * m_BytesPerEntry );
//            delete[] m_pData;
//        }
//        m_pData = pDataNew;
//        m_NumEntriesAllocated = NumEntriesAllocatedNew;
//    }
//
//    if( m_ArrayListType == AL_VALUE )
//        CopyMemory( (BYTE*)m_pData + (m_NumEntries * m_BytesPerEntry), pEntry, m_BytesPerEntry );
//    else
//        *(((void**)m_pData) + m_NumEntries) = pEntry;
//    m_NumEntries++;
//
//    return S_OK;
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: CArrayList::Remove
//// Desc: Remove the item at Entry in the list, and collapse the array. 
////-----------------------------------------------------------------------------
//void CArrayList::Remove( UINT Entry )
//{
//    // Decrement count
//    m_NumEntries--;
//
//    // Find the entry address
//    BYTE* pData = (BYTE*)m_pData + (Entry * m_BytesPerEntry);
//
//    // Collapse the array
//    MoveMemory( pData, pData + m_BytesPerEntry, ( m_NumEntries - Entry ) * m_BytesPerEntry );
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: CArrayList::GetPtr
//// Desc: Returns a pointer to the Entry'th entry in the list.
////-----------------------------------------------------------------------------
//void* CArrayList::GetPtr( UINT Entry )
//{
//    if( m_ArrayListType == AL_VALUE )
//        return (BYTE*)m_pData + (Entry * m_BytesPerEntry);
//    else
//        return *(((void**)m_pData) + Entry);
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: CArrayList::Contains
//// Desc: Returns whether the list contains an entry identical to the 
////       specified entry data.
////-----------------------------------------------------------------------------
//bool CArrayList::Contains( void* pEntryData )
//{
//    for( UINT iEntry = 0; iEntry < m_NumEntries; iEntry++ )
//    {
//        if( m_ArrayListType == AL_VALUE )
//        {
//            if( memcmp( GetPtr(iEntry), pEntryData, m_BytesPerEntry ) == 0 )
//                return true;
//        }
//        else
//        {
//            if( GetPtr(iEntry) == pEntryData )
//                return true;
//        }
//    }
//    return false;
//}
//
//
//
//
////-----------------------------------------------------------------------------
//// Name: BYTE helper functions
//// Desc: cchDestChar is the size in BYTEs of strDest.  Be careful not to 
////       pass use sizeof() if the strDest is a string pointer.  
////       eg.
////       TCHAR* sz = new TCHAR[100]; // sizeof(sz)  == 4
////       TCHAR sz2[100];             // sizeof(sz2) == 200
////-----------------------------------------------------------------------------
//HRESULT DXUtil_ConvertAnsiStringToWideCb( WCHAR* wstrDestination, const CHAR* strSource, int cbDestChar )
//{
//    return DXUtil_ConvertAnsiStringToWideCch( wstrDestination, strSource, cbDestChar / sizeof(WCHAR) );
//}
//
//HRESULT DXUtil_ConvertWideStringToAnsiCb( CHAR* strDestination, const WCHAR* wstrSource, int cbDestChar )
//{
//    return DXUtil_ConvertWideStringToAnsiCch( strDestination, wstrSource, cbDestChar / sizeof(CHAR) );
//}
//
//HRESULT DXUtil_ConvertGenericStringToAnsiCb( CHAR* strDestination, const TCHAR* tstrSource, int cbDestChar )
//{
//    return DXUtil_ConvertGenericStringToAnsiCch( strDestination, tstrSource, cbDestChar / sizeof(CHAR) );
//}
//
//HRESULT DXUtil_ConvertGenericStringToWideCb( WCHAR* wstrDestination, const TCHAR* tstrSource, int cbDestChar )
//{
//    return DXUtil_ConvertGenericStringToWideCch( wstrDestination, tstrSource, cbDestChar / sizeof(WCHAR) );
//}
//
//HRESULT DXUtil_ConvertAnsiStringToGenericCb( TCHAR* tstrDestination, const CHAR* strSource, int cbDestChar )
//{
//    return DXUtil_ConvertAnsiStringToGenericCch( tstrDestination, strSource, cbDestChar / sizeof(TCHAR) );
//}
//
//HRESULT DXUtil_ConvertWideStringToGenericCb( TCHAR* tstrDestination, const WCHAR* wstrSource, int cbDestChar )
//{
//    return DXUtil_ConvertWideStringToGenericCch( tstrDestination, wstrSource, cbDestChar / sizeof(TCHAR) );
//}
//
//HRESULT DXUtil_ReadStringRegKeyCb( HKEY hKey, TCHAR* strRegName, TCHAR* strDest, DWORD cbDest, TCHAR* strDefault )
//{
//    return DXUtil_ReadStringRegKeyCch( hKey, strRegName, strDest, cbDest / sizeof(TCHAR), strDefault );
//}
//
//HRESULT DXUtil_ConvertGUIDToStringCb( const GUID* pGuidSrc, TCHAR* strDest, int cbDestChar )
//{
//    return DXUtil_ConvertGUIDToStringCch( pGuidSrc, strDest, cbDestChar / sizeof(TCHAR) );
//}
//
//#ifndef UNDER_CE
//HRESULT DXUtil_GetDXSDKMediaPathCb( TCHAR* szDest, int cbDest )
//{
//    return DXUtil_GetDXSDKMediaPathCch( szDest, cbDest / sizeof(TCHAR) );
//}
//
//HRESULT DXUtil_FindMediaFileCb( TCHAR* szDestPath, int cbDest, TCHAR* strFilename )
//{
//    return DXUtil_FindMediaFileCch( szDestPath, cbDest / sizeof(TCHAR), strFilename );
//}
//#endif // !UNDER_CE
